iT邦幫忙

2023 iThome 鐵人賽

DAY 10
1
自我挑戰組

複習 JavaScript 核心概念系列 第 10 篇

[Day 10] 非同步任務的兩種類型:Macrotask 與 MicroTask

  • 分享至 

  • xImage
  •  

昨天提到了瀏覽器中 事件循環(Event Loop) 整體的運作過程,但其中有個地方沒有深入介紹,那就是Macrotask 和 MicroTask。

注意,接下來會提到多種非同步操作,例如計時器(setTimeout、setInterval)、Promise、DOM事件處理(例如滑鼠點擊、鍵盤輸入的監聽器)、非同步函數(async 和 await)等等。本篇文章並不會詳述這些非同步操作的用法,而會聚焦到今天的主題 Macrotask 和 MicroTask 的差別與運作流程。

另外今天算是延續昨天的 事件循環(Event Loop) 的概念,最好先理解一下。


開始今天的主題,在事件循環中的 Callback Queue 中,
其實可以看成有兩條佇列:Macrotask(宏任務)和Microtask(微任務)。
非同步操作會依照類型不同而被排入兩條佇列的其中一條;而他們又會依照彼此的優先度而被取出執行。

Macrotask(宏任務)

Macrotask 是一個較大、較長的非同步任務,且在事件循環中具有較低的優先度。
例如:計時器(setTimeOut、setInterval),使用者互動(事件監聽器的 callback)等。

Microtask(微任務)

Microtask 是一個較小、較短的非同步任務,它的優先度較高,會在 Macrotask 之前執行。
例如:Promise 的then和catch、async function、process.nextTick()等。


以下是 Event Loop 處理 Macrotask 和 Microtask 流程圖(未知原始圖片來源)

上圖簡單來說,必須等所有的 microtask 佇列清空,才會檢查 macrotask 佇列並取出一個項目並執行。
但每執行完一個 macrotask ,都會再檢查 microtask 佇列並等待當下的 microtask 佇列清空,才會再回頭檢查 macrotask 佇列。

用動圖更好理解:


以下是一個實際的例子。

console.log('Start');
    
setTimeout(() => console.log('SetTimeout checked!'), 0);

Promise.resolve().then(() => console.log('Promise checked!'));

console.log('End');

而它們輸出順序的結果為:

Start
End
Promise checked!
SetTimeout checked!

首先我們知道setTimeout 和 Promise 都是非同步操作。
但因為 setTimeout 屬於 Macrotask,Promise 屬於 Microtask,
因此雖然 setTimeout 的回調函式先進入了 Callback Stack,
但 Promise 具有較高的優先級,
所以會先印出「Promise checked!」後才印出「SetTimeout checked!」。


總結

今天介紹了非同步操作依類型會被分為 Macrotask 與 MicroTask。
而MicroTask 的優先度高於 Macrotask,所以 事件循環(Event Loop) 在檢查 Call Stack 時會優先取出 MicroTask 並執行。

那麼今天就到這邊了,明天見 ~


上一篇
[Day 09] 不可不知的事件循環(Event Loop)
下一篇
[Day 11] JavaScript 可以不加分號?關於「自動分號插入(ASI)」
系列文
複習 JavaScript 核心概念 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言